/***********************************************
 **** 版权声明处 **
 ****  为了方便阅读和维护，请严格遵守相关代码规范，谢谢   ****
 *******************************************/
package bpm.graphic
{
	/*******************************************
	 **** huangjixin,2012-11-15,下午4:33:50 **
	 **** 请一句话表述该类主要作用  **
	 *******************************************/
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import mx.core.IFactory;
	import mx.core.UIComponent;
	import mx.managers.DragManager;
	
	import spark.components.supportClasses.SkinnableComponent;
	
	/**
	 * 该图表作为显示元素之用，其中包括拖拽等操作，主要通过stage对象进行事件交互。 
	 * @author huangjixin
	 * 
	 */
	[Event(name="dragDrop", type="mx.events.DragEvent")]
	[Event(name="dragEnter", type="mx.events.DragEvent")]
	public class Diagram extends SkinnableComponent
	{
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// private 类私有静态变量和静态常量声明处。（全部大写，使用下划线进行分割）
		// 例如：private static const EXAMPLE:String = "example";
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// public 类公有静态变量和静态常量声明处。（全部大写，使用下划线进行分割）
		// 例如：public static const EXAMPLE:String = "example";
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// public 公有变量声明处
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		[SkinPart]
		public var graph:Graph;
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// private 私有变量声明处，请以“_”开头定义变量
		// 例如：private var _example:String;
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		private var _allowMovingNodes : Boolean;
		
		private var _linkRenderer : IFactory;
		
		private var _nodeRendererFunction:Function;
		
		private var _selectedItem : Object;
		
		private var _selectedItems : Vector.<Object> = new Vector.<Object>();
		
		private var _selectionMode:String="multiple"
			
		private var _cloneFunction:Function = cloneFunction;
		
		private var _nodeDataProvider:Object;
		
		private var _nodeRenderer:IFactory;
		
		private var _currentUIComponent:UIComponent;
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// 构造函数，初始化相关工作可以放在里面
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		/**
		 * 构造器。 
		 * 
		 */
		public function Diagram()
		{
			super();
			
			addEventListener(Event.ADDED_TO_STAGE,onAddToStage);
		}//构造函数结束
		
		
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// getter和setter函数
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		public function get allowMovingNodes():Boolean
		{
			return _allowMovingNodes;
		}
		
		public function set allowMovingNodes(value:Boolean):void
		{
			_allowMovingNodes = value;
		}
		
		public function get linkRenderer():IFactory
		{
			return _linkRenderer;
		}
		
		public function set linkRenderer(value:IFactory):void
		{
			_linkRenderer = value;
		}
		//--------------------------
		// 格式：createNodeRenderer(diagram:Diagram,item:Object) : Node
		//--------------------------
		public function get nodeRendererFunction():Function
		{
			return _nodeRendererFunction;
		}
		
		public function set nodeRendererFunction(value:Function):void
		{
			_nodeRendererFunction = value;
		}
		
		public function get nodeDataProvider():Object
		{
			return _nodeDataProvider;
		}
		
		public function set nodeDataProvider(value:Object):void
		{
			_nodeDataProvider = value;
		}
		
		public function get nodeRenderer():IFactory
		{
			return _nodeRenderer;
		}
		
		public function set nodeRenderer(value:IFactory):void
		{
			_nodeRenderer = value;
		}
		
		public function get cloneFunction():Function
		{
			return _cloneFunction;
		}
		
		public function set cloneFunction(value:Function):void
		{
			_cloneFunction = value;
		}
		
		public function get selectedItem():Object
		{
			return _selectedItem;
		}
		
		public function set selectedItem(value:Object):void
		{
			_selectedItem = value;
		}
		
		public function get selectedItems():Vector.<Object>
		{
			return _selectedItems;
		}
		
		public function set selectedItems(value:Vector.<Object>):void
		{
			_selectedItems = value;
		}
		
		[Bindable]
		[Inspectable(enumeration="multiple,single,none",defaultValue="multiple")]
		public function get selectionMode():String
		{
			return _selectionMode;
		}
		
		public function set selectionMode(value:String):void
		{
			_selectionMode = value;
		}
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// 相关事件响应函数和逻辑函数存放处
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		public function clearSelection():void{
			while(selectedItems.length != 0){
				var ele:Renderer = selectedItems.pop();
				ele.isSelected = false;
			}
		}
		
		public function setItemSelected(item:Object, value:Boolean = true):void{
			if(item is Renderer){
				Renderer(item).isSelected = value;
			}
		}
		/**
		 * 添加到舞台的响应函数，在函数体当中添加侦听舞台移动事件，注意均在捕获阶段。 
		 * @param event
		 * 
		 */
		protected function onAddToStage(event:Event):void
		{
			stage.addEventListener(MouseEvent.MOUSE_DOWN,onStageMouseDown,true);
		}
		/**
		 * 获得舞台当中最前的节点。 
		 * @param event
		 * 
		 */
		protected function onStageMouseDown(event:MouseEvent):void
		{
			if(event.cancelable){
				return;
			}
			
			//-----------------------------------------
			// 通过坐标转换判断点击的区域是否在本地区域内，如果不是那就返回
			//-----------------------------------------
			var rect:Rectangle = this.getRect(graph);
			var point:Point = new Point(rect.x,rect.y);
			point = localToGlobal(point);
			rect.x = point.x;
			rect.y = point.y;
			
			point = new Point(graph.mouseX,graph.mouseY);
			point = localToGlobal(point);
			if(!rect.containsPoint(point)){
				return;
			}
			
			//-----------------------------------------
			// 先判断是否为多选，多选则选中的图元可以拖拽，单选就拖动本身；
			//-----------------------------------------
			var renderer:Renderer;
			renderer = graph.getHitRenderer();
			graph.setFocus();
			if(renderer){
				if(!graph.contains(renderer)){
					return;
				}
				
				var index:int = selectedItems.indexOf(renderer);
				
				if(selectionMode == "multiple"){
					renderer.addEventListener(MouseEvent.MOUSE_DOWN, onRenderMouseDown);
					if(event.ctrlKey){
						if(index == -1){
							setItemSelected(renderer);
							selectedItems.push(renderer);
						}else{
							setItemSelected(renderer,false);
							selectedItems.splice(index,1);
						}
					}else{
						if(index == -1){
							clearSelection();
							setItemSelected(renderer);
							selectedItems.push(renderer);
						}
					}
				}else if(selectionMode == "single"){
					renderer.addEventListener(MouseEvent.MOUSE_DOWN, onRenderMouseDown);
					
					clearSelection();
					setItemSelected(renderer);
					selectedItems.push(renderer);
				}else if(selectionMode == "none"){
					clearSelection();
				}
				
			}else if(event.target == graph){
				clearSelection();
				
				if(selectionMode == "single"){
					graph.addEventListener(MouseEvent.MOUSE_DOWN, onRenderMouseDown);
				}
			}
		}	
		
		/**
		 * 当元素被鼠标按下的时候，做拖拽准备。 
		 * @param event
		 * 
		 */
		protected function onRenderMouseDown(event:MouseEvent):void
		{
			//--------------------------------
			// 不对不是Renderer节点做拖拽移动。
			//--------------------------------
			if(!allowMovingNodes){
				return;
			}
			//先把变量给定义好。
			var renderer:UIComponent = event.currentTarget as UIComponent;
			_currentUIComponent = renderer;
			//拖拽开始。
			renderer.startDrag();
			
			renderer.stage.addEventListener(MouseEvent.MOUSE_UP, onRendererMouseUp);
			
			//必须先截住事件。
			event.stopPropagation();
		}
		
		/**
		 * 节点鼠标弹起响应函数，停止拖拽，移除弹起侦听器，当前节点对象设置为null。 
		 * @param event
		 * 
		 */
		protected function onRendererMouseUp(event:Event):void
		{
			if(_currentUIComponent){
				_currentUIComponent.stage.addEventListener(MouseEvent.MOUSE_UP, onRendererMouseUp);
				_currentUIComponent.stopDrag();
				_currentUIComponent = null;
			}
		}
		
		private function cloneFun(obj:Renderer, clone:Renderer) : void 
		{
			if(clone is Node){
				clone.width = 200;
				clone.height = 100;
			}           
		} 
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		// override 覆盖函数
		//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
		override protected function partAdded(partName:String, instance:Object):void{
			super.partAdded(partName, instance);
			if(instance == graph){
				graph.cloneFunction = cloneFunction;
			}
		} 


	}//类结束
}//包结束